#include "stack.h"

struct _stack_ {
	void **data;
	int size;
	int top;
};
stack_s * stack_create(int size)
{
	stack_s *stack = (stack_s *)malloc(sizeof(stack_s));

	stack->size = 0;
	stack->top = 0;
	if (stack != NULL && size > 0) {
		stack->data = (void  **)malloc(size*sizeof(void *));
		if (stack->data != NULL) {
			stack->size = size;
		}
	}
	return stack;
}
void  stack_destory(stack_s * stack)
{
	if (stack != NULL) {
		if (stack->data != NULL) {
			free(stack->data);
		}
		free(stack);
	}
}


ret_e stack_push(stack_s *stack,void * data)
{
	if (stack == NULL) {
		return RET_PRA;
	}
	if (stack->top == stack->size ) {
		stack->data = (void **)realloc(stack->data,\
					((stack->size + stack->size)>>2) *sizeof(void *));
		if (stack->data != NULL) {
			stack->size = (stack->size +(stack->size>>2) );
		}
	}  
	if (stack->data == NULL) {
		return RET_MEM;
	}
	stack->data[stack->top] = data;
	stack->top++;
	return RET_OK;
}

ret_e stack_pop(stack_s *stack,void ** data)
{
	if (stack == NULL) {
		return RET_PRA;
	}
	if (stack->top <= 0){
		return RET_END;
	}
	stack->top--;
	if (data != NULL) {
		*data  = (stack->data[stack->top]);
	}
	return RET_OK;
}

ret_e stack_top(stack_s *stack,void ** data)
{
	if (stack == NULL) {
		return RET_PRA;
	}
	if (stack->top <= 0){
		return RET_END;
	}
	stack->top--;
	if (data != NULL) {
		*data  = (stack->data[stack->top]);
	}
	stack->top++;
	return RET_OK;
}

ret_e stack_is_empty(stack_s * stack)
{
	if (stack->top <= 0){
		return RET_END;
	}
	return RET_OK;
}

int stack_length(stack_s * stack)
{
	return stack->top;
}

ret_e stack_get_by_index(stack_s *stack,void ** data,int index)
{
	if (stack == NULL) {
		return RET_PRA;
	}
	if (stack->top <= 0){
		return RET_END;
	}
	if (index > stack->top) {
		return RET_END;
	}
	index--;
	if (data != NULL) {
		*data  = (stack->data[index]);
	}
	return RET_OK;
}
ret_e stack_for_loop(stack_s *stack,loop_fun_f loop_fun,void **context)
{
	int index = 0;
	
	if (stack == NULL || loop_fun == NULL) {
		return RET_PRA;
	}
	if (stack->top <= 0){
		return RET_END;
	}
	while (index <  stack->top) {
		if (loop_fun(stack->data[index],context) == RET_END) {
			break;
		}
		index++;
	}
	return RET_OK;
}
ret_e stack_print(stack_s *stack,loop_fun_f print_fun)
{
	return stack_for_loop(stack,print_fun,NULL);
}